package modele;

import java.awt.Color;
import java.io.Serializable;


/**
 * La classe Point représente un point grâce à deux attributs qui sont ses coordonnées sur le canevas :<br>
 * <ul>
 * <li>x</li>
 * <li>y</li>
 * </ul>
 * @author amm
 *
 */

public class Point extends FormeGeometrique implements Serializable {
	
	/**
	 * Premier attribut du point qui correspond à sa position en x
	 */
	private int x;
	/** Deuxieme attribut du point qui correspond à sa position en y
	 * 
	 */
	private int y;


/**
 * Constructeur par défaut qui va créer un point de coordonnées (0,0)
 */
	public Point() {
		x = 0;
		y = 0;
	}

/**
 * Constructeur qui prend en parametre deux entiers qui seront respectivement x et y
 * @param a
 * @param b
 */
	public Point(int a, int b) {
		x = a;
		y = b;
	}
	
	/**
	 * 	Constructeur qui prend en parametre deux entiers et un objet Color qui seront respectivement x, y et la couleur du Point
	 *
	 * @param a
	 * @param b
	 * @param c
	 */

	public Point(int a, int b, Color c) {
		this.x = a;
		this.y = b;
		this.couleur = c;
		
	}

	/** Constructeur qui prend en parametre deux entiers, un objet Color et un objet String
	 * qui seront respectivement x, y, la couleur du point et le nom du point.
	 * 
	 * @param x
	 * @param y
	 * @param couleur
	 * @param nom
	 */

	public Point(int x, int y, Color couleur, String nom) {
		this.x = x;
		this.y = y;
		this.couleur = couleur;
		this.nom = nom;
	}

	
	/**
	 * Constructeur secondaire qui retourne un objet de type Point ayant les mêmes 
	 * attributs que le point en question : <br>
	 * <ul>
	 * <li>x</li>
	 * <li>y</li>
	 * <li>z</li>
	 */
	public Point createClone() {
		Point Clone = new Point(this.getX(), this.getY(), this.getCouleur(), this.getNom());
		return Clone;
	}
	

	/**
	 * Constructeur secondaire qui retourne un objet de type Point qui correspond
	 * à une symetrie par rapport à l'origine du point en question. Le parametre origine
	 * correpond au Point désignant l'origine sur le canevas
	 * @param origine
	 */
	
	public Point createSymetrieO(Point origine) {
		int ecartx = 2*(this.getX()-origine.getX());
		int ecarty = 2*(this.getY()-origine.getY());
		Point Resultat = new Point(this.x -ecartx, this.y-ecarty, this.couleur);
		return Resultat;
	}

	/**
	 * Constructeur secondaire qui retourne un objet de type Point qui correspond
	 * à une symetrie par rapport à l'axe des abscisses du point en question. Le parametre origine
	 * correpond au Point désignant l'origine sur le canevas
	 * @param origine
	 */
	public Point createSymetrieX(Point origine) {
		//Point Resultat = new Point(this.getX(), -this.getY());
		int ecarty = 2*(this.getY()-origine.getY());
		Point Resultat = new Point(this.x, this.y-ecarty, this.couleur);
		return Resultat;
	}

	/**
	 * Constructeur secondaire qui retourne un objet de type Point qui correspond
	 * à une symetrie par rapport à l'axe des ordonnées du point en question. Le parametre origine
	 * correpond au Point désignant l'origine sur le canevas
	 * @param origine
	 */
	public Point createSymetrieY(Point origine) {
		//Point Resultat = new Point(-this.getX(), this.getY());
		int ecartx = 2*(this.getX()-origine.getX());
		Point Resultat = new Point(this.x -ecartx, this.y,this.couleur);
		return Resultat;
	}

	
	/**
	 * Retourne la coordonnée x
	 * @return la coordonnée x sous la forme d'un entier
	 */
	public int getX() {
		return x;
	}

	/**
	 * Retourne la coordonnée y
	 * @return la coordonnée y sous la forme d'un entier
	 */
	public int getY() {
		return y;
	}

	/**
	 * Retourne la distance entre deux points
	 * @param loin
	 * @return la distance entre deux points sous la forme d'un entier
	 */

	public double distance(Point loin) {
		int xa = this.x;
		int ya = this.y;
		int xb = loin.x;
		int yb = loin.y;

		double distance = Math
				.sqrt(Math.pow(xb - xa, 2) + Math.pow(yb - ya, 2));
		return distance;
	}

	/**
	 * Affiche des informations sur le point
	 * @return des informations sur le point sous la forme d'une chaine de caractere
	 */
	public String toString() {
		String rapport = new String("Coordonnées du point (X,Y) : ("
				+ this.getX() + "," + this.getY() + ")");
		return rapport;
	}

	public double perimetre() {
		return 0;
	}

	public double surface() {
		return 0;
	}

	// observateurs relationels

	/*
	 * On veut redefinir le equals. pour ça il faut avoir la meme signature donc
	 * l'argument doit etre une forme geometrique.
	 * 
	 * on redefinit en utilisant la meme signature. Probleme : notre equals peut
	 * prendre n'importe quoi. Solution : on test qu'on a bien un Point
	 * 
	 * Du coup vu qu'on prend un FormeGeometrique et qu'on veut comparer x et y
	 * .... pour la forme geometrique ça n'existe pasdonc on doit CASTER notre
	 * sujet(argument)
	 */
	
	/**
	 * Permet de comparer la position de deux points
	 * @return un boolean qui vaut TRUE si les deux points ont une position identique
	 * @param sujet
	 */
	public boolean equals(FormeGeometrique sujet) {
		if (sujet instanceof Point) {
			return (this.x == ((Point) sujet).x && this.y == ((Point) sujet).y);
		} else {
			return false;
		}
	}

	
//	public int compare(Point sujet) {
//
//		Point Origine = new Point(0, 0);
//
//		double dthiszero = this.distance(Origine);
//		double dsujetzero = sujet.distance(Origine);
//
//		if (dthiszero == dsujetzero)
//			return 0;
//		if (dthiszero > dsujetzero)
//			return 1;
//		if (dthiszero < dsujetzero)
//			return -1;
//		return 2;
//
//	}
	
	
	/**
	 * Cette méthode compare la position de deux points et renvoie un int suivant le résultat.<br>
		Il y a 9 positions possibles :<br>
		<ul>
		<li>0 : le point sujet est en haut a gauche du point</li>
		<li>1 : le point sujet est en haut a droite du point</li>
		<li>2 : le point sujet est en bas a gauchedu point</li>
		<li>3 : le point sujet est en bas a gauchedu point</li>
		<li>4 : le point sujet est au dessus du point</li>
		<li>5 : le point sujet est en dessous du point</li>
		<li>6 : le point sujet est a gauche du point</li>
		<li>7 : le point sujet est a droite du point</li>
		<li>8 : les deux points sont identiques</li>
	 * @param sujet
	 * @return un integer qui correspond à la position relative des deux points.
	 */
	public int compareposition(Point sujet){

		
		if(sujet.getX() < this.getX() && sujet.getY() < this.getY()) return 0; //le point sujet est en haut a gauche du point
		if(sujet.getX() > this.getX() && sujet.getY() <this.getY()) return 1; // le point sujet est en haut a droite du point
		if(sujet.getX() < this.getX() && sujet.getY() > this.getY()) return 2;//le point sujet est en bas a gauchedu point
		if(sujet.getX() > this.getX() && sujet.getY() > this.getY()) return 3;//le point sujet est en bas a droite du point
		
		if(sujet.getX() == this.getX() && sujet.getY() < this.getY()) return 4;//le point sujet est au dessus du point
		if(sujet.getX() == this.getX() && sujet.getY() > this.getY()) return 5;//le point sujet est en dessous du point
		if(sujet.getY() == this.getY() && sujet.getX() < this.getX()) return 6;//le point sujet est a gauche du point
		if(sujet.getY() == this.getY() && sujet.getX() > this.getX())return 7;//le point sujet est a droite du point
		
		if(sujet.getX() == this.getX() && sujet.getY() == this.getY())return 8;//les deux points sont identiques
		return 69;
		
	}

	/**
	 * Met à jour la coordonnée x du point.
	 * @param n
	 */
	public void setX(int n) {
		this.x = n;
	}
	/**
	 * Met à jour la coordonée y du point
	 * @param n
	 */
	public void setY(int n) {
		this.y = n;
	}

	/**
	 * Met à jour les coordonées du point pour en faire un symetrie par rapport à l'origine<br>
	 * Le parametre origine correpond au Point désignant l'origine sur le canevas
	 * @param origine
	 */

	public void symetrieO(Point origine) {
		int ecartx = 2*(this.getX()-origine.getX());
		int ecarty = 2*(this.getY()-origine.getY());
		this.x = this.x -ecartx;
		this.y = this.y-ecarty;
	}
	
	
	/**
	 * Met à jour les coordonées du point pour en faire un symetrie par rapport à l'axe des abscisses<br>
	 * Le parametre origine correpond au Point désignant l'origine sur le canevas
	 * @param origine
	 */
	public void symetrieX(Point origine) {
		int ecarty = 2*(this.getY()-origine.getY());
		this.y = this.y-ecarty;
	}
	
	/**
	 * Met à jour les coordonées du point pour en faire un symetrie par rapport à l'axe des coordonées<br>
	 * Le parametre origine correpond au Point désignant l'origine sur le canevas
	 * @param origine
	 */
	public void symetrieY(Point origine) {
		int ecartx = 2*(this.getX()-origine.getX());
		this.x = this.x -ecartx;
	}

	/**
	 * Permet de modifier les coordonées du point en se basant la distance entre
	 * deux autres points : depart et destination
	 * @param depart
	 * @param destination
	 */
	@Override
	public void deplacer(Point depart, Point destination) {
		int decalageX = destination.getX()-depart.getX();
		int decalageY = destination.getY()-depart.getY();
		this.setX(this.getX()+decalageX);
		this.setY(this.getY()+decalageY);
	}

	/**
	 * Permet de savoir si un point (clic) est positionné sur le point avec une tolérance de 5 pixel
	 * @return un boolean qui vaut TRUE si le point clic est sur le point et qui vaut FALSE si le point clic n'y est pas
	 *@param clic 
	 */
	@Override
	public boolean isOnTheClick(Point clic) {
		int tolerance = 5;
		if (clic.getX() < this.getX()+tolerance && clic.getX() > this.getX()-tolerance && clic.getY() < this.getY()+tolerance && clic.getY() > this.getY()-tolerance) 
		{return true;}
		else return false;
	}
	
	
}